package com.gusti.mensajes.services.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gusti.mensajes.dao.IConversationThreadDao;
import com.gusti.mensajes.dao.IMessageDao;
import com.gusti.mensajes.dao.IUserDao;
import com.gusti.mensajes.dto.ConversationDto;
import com.gusti.mensajes.dto.MessageDto;
import com.gusti.mensajes.dto.UserDto;
import com.gusti.mensajes.model.ConversationThread;
import com.gusti.mensajes.model.Message;
import com.gusti.mensajes.model.User;
import com.gusti.mensajes.services.IMessageService;
import com.gusti.mensajes.util.ConstantsUtil;
import com.gusti.mensajes.util.DateUtil;
import com.gusti.mensajes.util.MessageResponse;

/**
 * 
 * @author gusti
 *
 */
@Service
public class MessageService implements IMessageService {

	@Autowired
	IConversationThreadDao conversationThreadDao;
	@Autowired
	IMessageDao messageDao;
	@Autowired
	IUserDao userDao;
	
	@Transactional
	public MessageResponse newUser( String userName ) {
		MessageResponse messageResponse = new MessageResponse();
		
		//creo usuario
		User user = new User();
		user.setName( userName );
		user.setUuid( UUID.randomUUID().toString() );
		
		//guardo usuario
		user = userDao.save( user );
		
		if( user.isNew() ) {
			messageResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {
			messageResponse.setData( new UserDto( user.getName(), user.getUuid() ) );
		}
		
		return messageResponse;
	}
	
	@Transactional
	public MessageResponse newMessage( String fromUserUuid, String toUserUuid, String messageText ) {
		MessageResponse messageResponse = new MessageResponse();
		
		//busco usuarios
		User fromUser = userDao.findUser( fromUserUuid );
		User toUser = userDao.findUser( toUserUuid );
		
		//busco posible conversacion
		ConversationThread conversationThread = messageDao.searchConversationThread( fromUser, toUser );
		
		//creo conversacion
		if( conversationThread.isNew() ) {
			conversationThread.setParticipantOne( fromUser );
			conversationThread.setParticipantTwo( toUser );
			conversationThread = conversationThreadDao.save( conversationThread );
		}
		
		//creo mensaje
		Message message = new Message();
		message.setOwner( fromUser );
		message.setMessage( messageText );
		message.setSendDate( DateUtil.createDateTime() );
		message.setConversationThread( conversationThread );
		
		//guardo mensaje
		message = messageDao.save( message );
		
		if( message.isNew() ) {
			messageResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {
			messageResponse.setData( "Enviado" );
		}

		return messageResponse;
	}

	public MessageResponse listUsers() {
		MessageResponse messageResponse = new MessageResponse();
		List<UserDto> userDtos = new ArrayList<UserDto>();
		
		//busco usuarios
		List<User> users = userDao.listUsers();
		
		//recupero nombre y uuid
		for ( User user : users ) {
			userDtos.add( new UserDto( user.getName() , user.getUuid() ) );
		}
		
		if( userDtos.isEmpty() ) {
			messageResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {
			messageResponse.setData( userDtos );
		}
		
		return messageResponse;
	}
	
	public MessageResponse listConversation( String userUuid ) {
		MessageResponse messageResponse = new MessageResponse();
		List<ConversationDto> listConversationDto  = new ArrayList<ConversationDto>();
		
		//busco usuario
		User user = userDao.findUser( userUuid );
		
		//recupero todos las conversaciones
		List<ConversationThread> conversationThreads = messageDao.listConversation( user );
		
		//recupero todos los usuarios menos yo y muestro la cantidad de mensajes
		for ( ConversationThread conversationThread : conversationThreads ) {
			ConversationDto conversationDto = new ConversationDto();
			if( !user.equals( conversationThread.getParticipantOne() ) ) {
				conversationDto.setUserName( conversationThread.getParticipantOne().getName() );
			}
			if( !user.equals( conversationThread.getParticipantTwo() ) ) {
				conversationDto.setUserName( conversationThread.getParticipantTwo().getName() );
			}
			conversationDto.setLastMessage( getLastMessage( conversationThread.getMessages() ) );
			conversationDto.setConversationId( conversationThread.getId() );
			conversationDto.setMessages( conversationThread.getMessages().size() );
			conversationDto.setUnreadMessages( getUnreadMessages( conversationThread.getMessages(), user ) );
			listConversationDto.add( conversationDto );
		}

		if( listConversationDto.isEmpty() ) {
			messageResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {
			messageResponse.setData( listConversationDto );
		}
		
		return messageResponse;
	}

	private String getLastMessage( List<Message> messages ) {
		
		return messages.get( messages.size() - 1 ).getMessage();
	}

	private int getUnreadMessages( List<Message> messages, User user ) {
		int unread = 0;
		
		for ( Message message : messages ) {
			if( !message.getOwner().equals( user ) ) {
				if( message.getReadDate() == null ) {
					unread++;
				}
			}
		}
		
		return unread;
	}
	
	@Transactional
	public MessageResponse viewConversation( String conversationId, String userUuid ) {
		MessageResponse messageResponse = new MessageResponse();
		List<MessageDto> messageDtos = new ArrayList<MessageDto>();
		
		//busco usuario
		User user = userDao.findUser( userUuid );
		
		//busco los mensajes
		List<Message> messages = messageDao.viewConversation( Long.valueOf( conversationId ).longValue() );
		
		//obtengo mensaje y fecha de envio
		for ( Message message : messages ) {
			MessageDto messageDto = new MessageDto();
			messageDto.setMessage( message.getMessage() );
			messageDto.setSendDate( DateUtil.getDateTime( message.getSendDate() ) );
//			messageDto.setUserRole( message.getOwner().equals( user ) ? MessageDto.TRANSMITTER : MessageDto.RECEPTOR );
			if( message.getOwner().equals( user ) ) {
				messageDto.setUserRole( MessageDto.SENDER );
			} else {
				messageDto.setUserRole( MessageDto.RECEPTOR );
				if( message.getReadDate() == null ) {
					message.setReadDate( DateUtil.createDateTime() );
					messageDao.update( message );
				}
			}
			messageDtos.add( messageDto );
		}
		
		if( messageDtos.isEmpty() ) {
			messageResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {
			messageResponse.setData( messageDtos );
		}
		
		return messageResponse;
	}
	
}
